/*
 * Copyright (C) 2012-2016 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.greenrobot.eventbus.util;

import ohos.aafwk.ability.Ability;
import ohos.agp.window.dialog.BaseDialog;
import ohos.utils.PacMap;

import org.greenrobot.eventbus.EventBus;

/**
 * Central class for app that want to use event based error dialogs.<br/>
 * <br/>
 * How to use:
 * <ol>
 * <li>Set the {@link #factory} to configure dialogs for your app, typically in {@link Application#onCreate()}</li>
 * <li>Use one of {@link #attachTo(Ability)}, {@link #attachTo(Ability, boolean)} or
 * {@link #attachTo(Ability, boolean, PacMap)} in your Activity, typically in onCreate.</li>
 * </ol>
 * <p>
 * For more complex mappings, you can supply your own {@link ErrorDialogFragmentFactory}.
 *
 * @author Markus
 */
public class ErrorDialogManager {

    public static class SupportManagerFragment {
        protected boolean finishAfterDialog;
        protected PacMap argumentsForErrorDialog;
        private EventBus eventBus;
        private boolean skipRegisterOnNextResume;
        private Object executionScope;

        public SupportManagerFragment(Ability ability) {

        }


        public void onCreate() {
            eventBus = ErrorDialogManager.factory.config.getEventBus();
            eventBus.register(this);
            skipRegisterOnNextResume = true;
        }

        public void onResume() {
            if (skipRegisterOnNextResume) {
                // registered in onCreate, skip registration in this run
                skipRegisterOnNextResume = false;
            } else {
                eventBus = ErrorDialogManager.factory.config.getEventBus();
                eventBus.register(this);
            }
        }

        public void onPause() {
            eventBus.unregister(this);
        }

        public void onEventMainThread(ThrowableFailureEvent event) {
            if (!isInExecutionScope(executionScope, event)) {
                return;
            }
            checkLogException(event);
            // Execute pending commits before finding to avoid multiple error fragments being shown

            BaseDialog errorDialog = (BaseDialog) factory
                    .prepareErrorFragment(event, finishAfterDialog, argumentsForErrorDialog);
            if (errorDialog != null) {
                errorDialog.show();
            }
        }

        public static void attachTo(Ability ability, Object executionScope, boolean finishAfterDialog,
                                    PacMap argumentsForErrorDialog) {
            SupportManagerFragment fragment = new SupportManagerFragment(ability);
            fragment.finishAfterDialog = finishAfterDialog;
            fragment.argumentsForErrorDialog = argumentsForErrorDialog;
            fragment.executionScope = executionScope;
        }
    }

    /**
     * Must be set by the application.
     */
    public static ErrorDialogFragmentFactory<?> factory;

    protected static final String TAG_ERROR_DIALOG = "de.greenrobot.eventbus.error_dialog";
    protected static final String TAG_ERROR_DIALOG_MANAGER = "de.greenrobot.eventbus.error_dialog_manager";

    public static final String KEY_TITLE = "de.greenrobot.eventbus.errordialog.title";
    public static final String KEY_MESSAGE = "de.greenrobot.eventbus.errordialog.message";
    public static final String KEY_FINISH_AFTER_DIALOG = "de.greenrobot.eventbus.errordialog.finish_after_dialog";
    public static final String KEY_ICON_ID = "de.greenrobot.eventbus.errordialog.icon_id";
    public static final String KEY_EVENT_TYPE_ON_CLOSE = "de.greenrobot.eventbus.errordialog.event_type_on_close";

    /**
     * Scope is limited to the activity's class.
<<<<<<< Updated upstream
=======
     *
     * @param activity Ability
>>>>>>> Stashed changes
     */
    public static void attachTo(Ability activity) {
        attachTo(activity, false, null);
    }

    /**
     * Scope is limited to the activity's class.
<<<<<<< Updated upstream
=======
     *
     * @param activity          Ability
     * @param finishAfterDialog dialog
>>>>>>> Stashed changes
     */
    public static void attachTo(Ability activity, boolean finishAfterDialog) {
        attachTo(activity, finishAfterDialog, null);
    }

    /**
     * Scope is limited to the activity's class.
<<<<<<< Updated upstream
=======
     *
     * @param activity                Ability
     * @param finishAfterDialog       finishAfterDialog
     * @param argumentsForErrorDialog argumentsForErrorDialog
>>>>>>> Stashed changes
     */
    public static void attachTo(Ability activity, boolean finishAfterDialog, PacMap argumentsForErrorDialog) {
        Object executionScope = activity.getClass();
        attachTo(activity, executionScope, finishAfterDialog, argumentsForErrorDialog);
    }

    /**
     * attachTo
     *
     * @param activity                Ability
     * @param executionScope          executionScope
     * @param finishAfterDialog       finishAfterDialog
     * @param argumentsForErrorDialog argumentsForErrorDialog
     */
    public static void attachTo(Ability activity, Object executionScope, boolean finishAfterDialog, PacMap argumentsForErrorDialog) {
        if (factory == null) {
            throw new RuntimeException("You must set the static factory field to configure error dialogs for your app.");
        }
        SupportManagerFragment.attachTo(activity, executionScope, finishAfterDialog, argumentsForErrorDialog);
    }

    protected static void checkLogException(ThrowableFailureEvent event) {
        if (factory.config.logExceptions) {
            String tag = factory.config.tagForLoggingExceptions;
            if (tag == null) {
                tag = EventBus.TAG;
            }
        }
    }

    private static boolean isInExecutionScope(Object executionScope, ThrowableFailureEvent event) {
        if (event != null) {
            Object eventExecutionScope = event.getExecutionScope();
            if (eventExecutionScope != null && !eventExecutionScope.equals(executionScope)) {
                // Event not in our scope, do nothing
                return false;
            }
        }
        return true;
    }

}
